package io.mqttpush.mqttserver.handles;


import io.mqttpush.common.events.OnLineEvent;
import io.mqttpush.mqttserver.auths.ConnectAuth;
import io.mqttpush.mqttserver.auths.EmbedAuthrize;
import io.mqttpush.mqttserver.config.DeviceManager;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.mqtt.*;
import io.netty.util.internal.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;
import java.util.List;

/**
 * 登录报文处理
 * @author tianzhenjiu
 * @date 2020/4/27 16:21
 */
public class LoginService implements Iservice<MqttConnectMessage>{



    Logger logger = LoggerFactory.getLogger(LoginService.class);

    ConnectAuth connectAuth=new EmbedAuthrize();

    @Override
    public boolean accept(ChannelHandlerContext context, MqttMessage inMessage) {

        return MqttMessageType.CONNECT==inMessage.fixedHeader().messageType();
    }

    @Override
    public List<Object> service(ChannelHandlerContext context, List<Object> outMessage, MqttConnectMessage inMessage) {


        logger.info("登录service");
        processLogin(context.channel(),inMessage,outMessage);

        return  outMessage;

    }


    /**
     * 处理登录
     * @param mqttConnectMessage
     */
   private void processLogin(Channel channel,MqttConnectMessage mqttConnectMessage, List<Object> outMessage){

        MqttConnectPayload payload= mqttConnectMessage.payload();

        /**
        * if there is no username  input data
        */
       String username= payload.userName();
        if(StringUtil.isNullOrEmpty(username)){
            logger.info("need the username for client{}",channel);

            outMessage.stream().findFirst().ifPresent((state)->{
                ((DispatchHandle.ProcessState)(state)).setState(DispatchHandle.ProcessStateEnum.error);
            });

            return;
        }

       /**
        * no password input data
        */
       String password=new String(payload.passwordInBytes());
       if(StringUtil.isNullOrEmpty(password)){
           logger.info("need the password for client{}",channel);

           outMessage.stream().findFirst().ifPresent((state)->{
               ((DispatchHandle.ProcessState)(state)).setState(DispatchHandle.ProcessStateEnum.error);
           });
           return;
       }

       String deviceId=payload.clientIdentifier();
       boolean isSuc=connectAuth.authorize(username,password);

       MqttConnectReturnCode  mqttConnectReturnCode=MqttConnectReturnCode.CONNECTION_REFUSED_NOT_AUTHORIZED;

       if(isSuc){

           /**
            * 添加事件
            */
           mqttConnectReturnCode=MqttConnectReturnCode.CONNECTION_ACCEPTED;

           DeviceManager.getDeviceManager().deviceLogin(username,deviceId,channel);


           OnLineEvent onLineEvent=new OnLineEvent();

           onLineEvent.deviceId=DeviceManager.getDeviceManager().deviceId(channel);
           onLineEvent.eventTime=new Date();
           onLineEvent.userInfo=username;

           outMessage.add(onLineEvent);
       }


       MqttFixedHeader fixedHeader = new MqttFixedHeader(MqttMessageType.CONNACK, false, MqttQoS.AT_MOST_ONCE, false,
               0);
       MqttConnAckVariableHeader connectVariableHeader = new MqttConnAckVariableHeader(mqttConnectReturnCode, false);

       outMessage.add(new MqttConnAckMessage(fixedHeader, connectVariableHeader));


   }

}
